package cvalidator

import (
	"gitee.com/theegg/go-brick/app/model/system/system_images"
	"gitee.com/theegg/go-brick/app/service/app"
	"gitee.com/theegg/go-brick/app/service/help/chtml"
	"github.com/go-playground/validator/v10"
	"regexp"
	"strconv"
	"strings"
)

// 默认字符串验证规则
var CustomNamePattern = `^[_A-Za-z0-9\p{Han}]+$`
var CustomSignPattern = `^[A-Za-z0-9]+$`
var CustomPhonePattern = `^(\+63)?(09|9|02)[0-9]{8,9}$`
var CustomWechatPattern = `^[a-zA-Z][a-zA-Z\d_\-]{5,19}$`
var CustomTelegramPattern = `^[a-zA-Z][a-zA-Z\d_\-]{5,19}$`

// 所有的新增校验方法需要添加到此
var RegisterItems = map[string]validator.Func{
	"customMin":         CustomMin,
	"customMax":         CustomMax,
	"customPlainText":   CustomPlainText,
	"customName":        CustomName,
	"customSign":        CustomSign,
	"customFiledUnique": CustomFiledUnique,
	"customUploadImage": CustomUploadImage,
	"customPhone":       CustomPhone,
	"customDateTime":    CustomDateTime,
	"customWechat":      CustomWechat,
}

// @title CustomMin
// @description 自定义长度, 中文算３个
func CustomMin(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}
	minLength, err := strconv.Atoi(fl.Param())
	if err != nil {
		return false
	}

	if len(value) < minLength {
		return false
	}

	return true
}

// @title CustomMax
// @description 自定义长度, 中文算３个
func CustomMax(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	maxLength, err := strconv.Atoi(fl.Param())
	if err != nil {
		return false
	}

	if len(value) > maxLength {
		return false
	}

	return true
}

// @title CustomPlainText
// @description 自定义检验字符串 自动去除ＨＴＭＬ标签
func CustomPlainText(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	cleanTitle := chtml.HtmlPlainText(value)

	if cleanTitle == "" {
		return false
	}

	params := fl.Param()
	if params == "" {
		return false
	}

	// 至少2个参数
	paramsArr := strings.Split(params, " ")
	if len(paramsArr) != 2 {
		return false
	}

	// 长度需要有效的整形
	minLength, err := strconv.Atoi(paramsArr[0])
	if err != nil {
		return false
	}

	maxLength, err := strconv.Atoi(paramsArr[1])
	if err != nil {
		return false
	}

	// 长度判断 中文3个字符
	if len(cleanTitle) < minLength || len(cleanTitle) > maxLength {
		return false
	}

	return true
}

// @title CustomName
// @description 自定义检验字符串 汉字/字母/数字/下划线
func CustomName(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	params := fl.Param()
	if params == "" {
		return false
	}

	// 至少2个参数
	paramsArr := strings.Split(params, " ")
	if len(paramsArr) != 2 {
		return false
	}

	// 长度需要有效的整形
	minLength, err := strconv.Atoi(paramsArr[0])
	if err != nil {
		return false
	}

	maxLength, err := strconv.Atoi(paramsArr[1])
	if err != nil {
		return false
	}

	// 长度判断 中文3个字符
	if len(value) < minLength || len(value) > maxLength {
		return false
	}

	// 正则匹配
	res, err := regexp.MatchString(CustomNamePattern, value)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}

// @title CustomSign
// @description 自定义检验字符串 字母/数字
func CustomSign(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	params := fl.Param()
	if params == "" {
		return false
	}

	// 至少2个参数
	paramsArr := strings.Split(params, " ")
	if len(paramsArr) != 2 {
		return false
	}

	// 长度需要有效的整形
	minLength, err := strconv.Atoi(paramsArr[0])
	if err != nil {
		return false
	}

	maxLength, err := strconv.Atoi(paramsArr[1])
	if err != nil {
		return false
	}

	// 长度判断 中文3个字符
	if len(value) < minLength || len(value) > maxLength {
		return false
	}

	// 正则匹配
	res, err := regexp.MatchString(CustomSignPattern, value)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}

// 字段在表中唯一
func CustomFiledUnique(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	params := fl.Param()
	if params == "" {
		return false
	}

	// 至少2个参数
	paramsArr := strings.Split(params, " ")
	if len(paramsArr) != 2 {
		return false
	}

	// 长度需要有效的整形
	tableName := paramsArr[0]
	fieldName := paramsArr[1]

	// 判断更性的情况
	idValue := fl.Parent().Elem().FieldByName("Id").Int()

	var id int
	var has bool
	var err error
	if idValue > 0 {
		has, err = app.Db().SQL("select id from "+tableName+" where "+fieldName+" = ? AND id != ?", value, idValue).Get(&id)
	} else {
		has, err = app.Db().SQL("select id from "+tableName+" where "+fieldName+" = ?", value).Get(&id)
	}

	if err != nil {
		return false
	}

	if has {
		return false
	}

	return true
}

/**
 * 图片上传的格式校验
 */
func CustomUploadImage(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	params := fl.Param()
	if params == "" {
		return false
	}

	// 可能存在多个参数
	paramsArr := strings.Split(params, " ")

	// 多图校验
	var imageList []string
	if len(paramsArr) == 2 && paramsArr[1] == "m" {
		imageList = strings.Split(value, ",")
	} else {
		imageList = []string{value}
	}

	// 校验格式
	for _, imageName := range imageList {
		// 格式判定
		if !system_images.ImageIsValidFormat(imageName, paramsArr[0]) {
			return false
		}
	}

	return true
}

// @title CustomPhone
// @description 自定义检验字符串 字母/数字
func CustomPhone(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	// 正则匹配
	res, err := regexp.MatchString(CustomPhonePattern, value)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}

// @title CustomWechat
// @description 校验微信
func CustomWechat(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	// 正则匹配
	res, err := regexp.MatchString(CustomWechatPattern, value)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}

// @title CustomTime
// @description 自定义检验字符串 字母/数字
func CustomDateTime(fl validator.FieldLevel) bool {
	value := fl.Field().Interface().(string)

	// 不负责判定required
	if value == "" {
		return true
	}

	formatType := "yyyy-mm-dd hh:ii:ss"
	params := fl.Param()
	if params != "" {
		formatType = params
	}

	pattern := ""
	switch formatType {
	case "yyyy-mm-dd hh:ii:ss":
		pattern = `^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$`
	case "yyyy-mm-dd":
		pattern = `^[0-9]{4}-[0-9]{2}-[0-9]{2}$`
	case "hh:ii:ss":
		pattern = `^[0-9]{2}:[0-9]{2}:[0-9]{2}$`
	case "hh:ii":
		pattern = `^[0-9]{2}:[0-9]{2}$`
	default:
		return false
	}

	// 正则匹配
	res, err := regexp.MatchString(pattern, value)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}
